package basic.xiazheng.encode;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * @创建人 MBY381
 * @创建时间 2022/4/24 15:34
 * @描述
 * 百度百科中对Base64有一个很好的解释：“Base64是网络上最常见的用于传输8Bit字节码的编码方式之一
 * Base64就是一种基于64个可打印字符来表示二进制数据的方法”。
 * 上面我们已经看到了Base64就是用6位（2的6次幂就是64）表示字符，因此成为Base64。
 * 同理，Base32就是用5位，Base16就是用4位。大家可以按照上面的步骤进行演化一下。
 *
 * 这64个字符是各种字符编码（比如ASCII编码）所使用字符的子集，基本，并且可打印。唯一有点特殊的是最后两个字符，因对最后两个字符的选择不同，Base64编码又有很多变种，比如Base64 URL编码。
 *
 * Base64编码本质上是一种将二进制数据转成文本数据的方案。对于非二进制数据，
 * 是先将其转换成二进制形式，然后每连续6比特（2的6次方=64）计算其十进制值，根据该值在上面的索引表中找到对应的字符，最终得到一个文本字符串。
 *
 * 具体转换步骤：
 *
 * 　　第一步 　　将待转换的字符串转为一个个字符
 * 　　第二步　　计算每一个字符对应的ASCII码十进制
 * 　　第三步　　计算出十进制对应的二进制，若不足8位，在前面添加0进行补全
 * 　　第四步　　将8位的二进制码，按照6个6个一组划分，若不能整除6，在最末添加0补足6位
 * 　　第五步 　　计算对应的十进制编码
 * 　　第六步 　　按照base64表，查看对应的字符
 * 　　第七步 　　将加密后的字符3个3个分成一组，不足3位的添加=进行补全
 * 　　第八步 　　得到最终结果
 *
 * 同时得到base64位编码后的特征：
 * 　　1）长度是3的倍数
 * 　　2）只含有65中字符，大写的A至Z，小写的a至z,数字0到9，以及3种符号+/ =，=最多两个，且在末尾
 *
 *
 * 切忌误用
 * 　　可能会有人在不理解Base64编码的情况下，将其误用于数据加密或数据校验。
 *
 * 　　Base64是一种数据编码方式，目的是让数据符合传输协议的要求。
 * 标准Base64编码解码无需额外信息即完全可逆，即使你自己自定义字符集设计一种类Base64的编码方式用于数据加密，在多数场景下也较容易破解。
 *
 *
 * 我认为，理解Base64或其他类似编码的关键有两点：
 *
 * 计算机最终存储和执行的是01二进制序列，这个二进制序列的含义则由解码程序/解释程序决定
 * 很多场景下的数据传输要求数据只能由简单通用的字符组成，比如HTTP协议要求请求的首行和请求头都必须是ASCII编码
 *
 * Base64编码应用
 * 本文开始提到的青云应用例子只是Base64编码的应用场景之一。
 * 由于Base64编码在字符集大小与编码后数据长度之间做了较好的平衡，以及Base64编码变种形式的多样，使得Base64编码的应用场景非常广泛。下面举2个常用常见的例子。
 */
public class Base64Test {
    public static void main(String[] args) throws UnsupportedEncodingException {
        // 编码
        String encode = Base64.getEncoder().encodeToString("Son".getBytes(StandardCharsets.UTF_8));
        System.out.println(encode);
        // 解码
        byte[] decode = Base64.getDecoder().decode(encode);
        System.out.println(new String(decode, StandardCharsets.UTF_8));
    }
}
